package com.doeis.common.utils;

import java.util.Date;
import java.util.Map;
import java.util.Timer;
import java.util.TimerTask;
import java.util.concurrent.*;
import java.util.concurrent.atomic.AtomicInteger;

/**
 * 任务引擎，在指定是时间或者立即执行特定的任务，所有执行的任务都在指定的线程池中。
 * 如果在指定的时间执行特定任务时，线程池中没有空闲的线程，那么这个任务也将排队等待有空闲的线程。
 * 这个任务引擎你可以看成是有线程管理的{@link Thread} 或者是{@line TimerTask}.
 * @author nortan
 *
 */
public class TaskEngine {

    private static TaskEngine instance = new TaskEngine();

    /**
     * 返回一个任务引擎实例
     * @return
     */
    public static TaskEngine getInstance() {
        return instance;
    }

    private Timer timer;	//定时器
    private ExecutorService executor; //执行管理服务
    private Map<TimerTask, TimerTaskWrapper> wrappedTasks = new ConcurrentHashMap<TimerTask, TimerTaskWrapper>();
    private boolean daemon = true;
    
    /**
     * 构造一个新的引擎
     */
    private TaskEngine() {
        timer = new Timer("timer-openfire", daemon);
        executor = Executors.newCachedThreadPool(new ThreadFactory() {
            final AtomicInteger threadNumber = new AtomicInteger(1);
            public Thread newThread(Runnable runnable) {
                // 使用我们自己的线程命名方式
                Thread thread = new Thread(Thread.currentThread().getThreadGroup(), runnable,
                                      "pool-netmachine" + threadNumber.getAndIncrement(), 0);
                // 设置任务为守护进程
                thread.setDaemon(daemon);
                if (thread.getPriority() != Thread.NORM_PRIORITY) {
                    thread.setPriority(Thread.NORM_PRIORITY);
                }
                return thread;
            }
        });
    }

    /**
     * 提交一个实时执行的任务也是需要排队的
     * @param task
     * @return
     */
    public Future<?> submit(Runnable task) {
        return executor.submit(task);
    }

    /**
     * 延迟时间来执行特定的task
     * @param task
     * @param delay 延迟的时间,单位：毫秒
     */
    public void schedule(TimerTask task, long delay) {
    	TimerTaskWrapper taskWrapper = new TimerTaskWrapper(task, true);
    	wrappedTasks.put(task, taskWrapper);
        timer.schedule(taskWrapper, delay);
    }

    /**
     * 在指定时间执行任务
     * @param task
     * @param time
     */
    public void schedule(TimerTask task, Date time) {
    	TimerTaskWrapper taskWrapper = new TimerTaskWrapper(task, true);
//    	wrappedTasks.put(task, taskWrapper);
        timer.schedule(taskWrapper, time);
    }

    /**
     * 延迟一定时间后，固定延时执行循环执行任务，可以参看{@link Timer#schedule()}
     * @param task
     * @param delay
     * @param period，循环任务间的间隔时间，以毫秒为单位
     */
    public void schedule(TimerTask task, long delay, long period) {
        TimerTaskWrapper taskWrapper = new TimerTaskWrapper(task, false);
        wrappedTasks.put(task, taskWrapper);
        timer.schedule(taskWrapper, delay, period);
    }

    /**
     * 在指定的时间执行第一次任务，以后循环执行
     * @param task
     * @param firstTime
     * @param period
     */
    public void schedule(TimerTask task, Date firstTime, long period) {
        TimerTaskWrapper taskWrapper = new TimerTaskWrapper(task, false);
        wrappedTasks.put(task, taskWrapper);
        timer.schedule(taskWrapper, firstTime, period);
    }

   /***
    * 延迟一定时间后，以固定速率执行循环执行任务，用来执行绝对 时间敏感的重复执行活动，如每小时准点打钟报时等等。
    * @param task
    * @param delay
    * @param period
    */
    public void scheduleAtFixedRate(TimerTask task, long delay, long period) {
        TimerTaskWrapper taskWrapper = new TimerTaskWrapper(task, false);
        wrappedTasks.put(task, taskWrapper);
        timer.scheduleAtFixedRate(taskWrapper, delay, period);
    }

    /**
     * 
     * @param task
     * @param firstTime 第一次执行时间
     * @param period 固定速率间隔时间
     */
    public void scheduleAtFixedRate(TimerTask task, Date firstTime, long period) {
        TimerTaskWrapper taskWrapper = new TimerTaskWrapper(task, false);
        wrappedTasks.put(task, taskWrapper);
        timer.scheduleAtFixedRate(taskWrapper, firstTime, period);
    }

    /**
     * 取消任务执行 {@link java.util.TimerTask#cancel()}
     *
     * @param task 需要取消的任务.
     */
    public void cancelScheduledTask(TimerTask task) {
        TaskEngine.TimerTaskWrapper taskWrapper = wrappedTasks.remove(task);
        if (taskWrapper != null) {
            taskWrapper.cancel();
        }
    }

    /**
     * 关闭任务服务
     */
    public void shutdown() {
        if (executor != null) {
            executor.shutdownNow();
            executor = null;
        }

        if (timer != null) {
            timer.cancel();
            timer = null;
        }
    }
    
    private class TimerTaskWrapper extends TimerTask {

        private TimerTask task;
        private boolean exeOnce;// 是否只执行一次

        public TimerTaskWrapper(TimerTask task, boolean exeOnce) {
            this.task = task;
            this.exeOnce = exeOnce;
        }
        public void run() {
            executor.submit(task);
            if(exeOnce){
            	wrappedTasks.remove(task);
            }
        }
    }
}